package core

import (
	"fmt"

	"game-simple/internal/infrastructure/config"
	"game-simple/internal/infrastructure/database"
	"game-simple/internal/infrastructure/logger"
	"game-simple/internal/infrastructure/redis"
	"game-simple/internal/infrastructure/websocket"
)

// Infrastructure 基础设施管理器
type Infrastructure struct {
	DB        database.DBWrapper
	Cache     redis.Cache
	Logger    logger.LoggerWrapper
	WebSocket *websocket.Wrapper
}

var instance *Infrastructure

// Init 初始化所有基础设施
func Init() error {
	cfg := config.GetConfig()
	if cfg == nil {
		return fmt.Errorf("配置未加载")
	}

	// 初始化数据库（必需）
	if err := database.InitMySQL(); err != nil {
		return err
	}

	// 初始化 Redis（根据配置决定是否必需）
	if cfg.Redis.Enabled {
		if err := redis.InitRedis(); err != nil {
			if cfg.Redis.Required {
				return fmt.Errorf("Redis 初始化失败（必需）: %w", err)
			}
			// Redis 非必需时，继续执行但输出警告
			fmt.Printf("⚠️  Redis 初始化失败（可选，继续运行）: %v\n", err)
		}
	} else {
		fmt.Println("ℹ️  Redis 已禁用（配置中 enabled: false）")
	}

	// 初始化日志（根据配置决定是否必需）
	if err := logger.InitLogger(); err != nil {
		if cfg.Log.Required {
			return fmt.Errorf("日志初始化失败（必需）: %w", err)
		}
		// 日志非必需时，继续执行但输出警告
		fmt.Printf("⚠️  日志初始化失败（可选，继续运行）: %v\n", err)
	}

	// 创建基础设施实例（即使某些组件失败也创建，避免 nil 引用）
	instance = &Infrastructure{
		DB:        database.NewDB(),
		Cache:     redis.NewCache(),  // 即使 Redis 失败，也创建包装器
		Logger:    logger.NewLogger(), // 即使日志失败，也创建包装器
		WebSocket: websocket.NewWrapper(), // WebSocket 始终可用
	}

	// 如果启用自动迁移，执行数据库迁移
	if config.GetConfig() != nil && config.GetConfig().Database.AutoMigrate {
		// 优先使用版本化迁移（如果存在迁移文件）
		if err := database.RunMigrations(); err != nil {
			// 如果版本化迁移失败，回退到 AutoMigrate
			instance.Logger.Warnf("版本化迁移失败，使用 AutoMigrate: %v", err)
			if err := database.AutoMigrate(); err != nil {
				instance.Logger.Errorf("数据库自动迁移失败: %v", err)
				return err
			}
			instance.Logger.Info("数据库自动迁移完成（使用 AutoMigrate）")
		} else {
			instance.Logger.Info("数据库版本化迁移完成")
		}
	}

	// 初始化种子数据（编号规则等，包括房间号规则）
	initSeedData()

	return nil
}

// Get 获取基础设施实例
func Get() *Infrastructure {
	if instance == nil {
		panic("基础设施未初始化，请先调用 core.Init()")
	}
	return instance
}

// Close 关闭所有基础设施连接
func Close() error {
	if instance == nil {
		return nil
	}

	var err error
	if closeErr := instance.DB.Close(); closeErr != nil {
		err = closeErr
	}
	if closeErr := instance.Cache.Close(); closeErr != nil {
		err = closeErr
	}
	if closeErr := instance.Logger.Sync(); closeErr != nil {
		err = closeErr
	}
	if closeErr := instance.WebSocket.Close(); closeErr != nil {
		err = closeErr
	}

	return err
}

